package com.designpattern.creating.singleton;

/**
 * @Author chengzelee
 * @Date 2022/11/24 18:36
 * @Desc 双重锁校验实现单例
 *       方法级锁较少阻塞
 */
public class Singleton_doubleLock {

    /**
     * singleton = new Singleton_doubleLock();
     * 拆分3个步骤：
     * 1 .分配内存空间；
     * 2. new Singleton() 初始化
     * 3. 对象内存引用赋值给singleton
     * 不加volatile的情况下：第2步和第3步可能会被重排序执行序列 1-3-2
     *
     * 多线程访问情况：
     * 线程1：执行顺序 1-3-2
     * 线程2：如果线程1执行到 3，这个时候线程2会在第一次检查是否为空时候发现对象不为空，返回一个没有正确初始化的对象并使用 ，从而导致系统异常
     *
     * 加上volatile：
     * volatile 修饰的变量会在写的前后加上内存屏障，禁止指令重排序 ，所以执行顺序就只会是1-2-3，
     * 线程2 发现singleton 不为空的时候一定是一个初始化成功的对象，从而保证系统正常
     */
    private static volatile Singleton_doubleLock instance;

    public static Singleton_doubleLock getInstance() {
        if (instance != null){
            return instance;
        }
        synchronized (Singleton_doubleLock.class){
            if (instance == null){
                instance = new Singleton_doubleLock();
            }
        }
        return instance;
    }
}
